home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / oleo_src.lha / src / regions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-18  |  18.7 KB  |  902 lines

  1. /*    Copyright (C) 1990 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20.  
  21. #include <stdio.h>
  22. #include "sysdef.h"
  23.  
  24. #include "global.h"
  25. #include "cell.h"
  26.  
  27. /* Define REVERSE only if it is also defined in cell.c */
  28. #define REVERSE
  29.  
  30. extern unsigned short get_width EXT1(CELLREF);
  31. extern CELLREF max_row EXT1(CELLREF);
  32. extern CELLREF max_col EXT1(CELLREF);
  33.  
  34. extern char *print_cell EXT1(CELL *);
  35. extern void pr_cell EXT3(CELLREF, CELLREF, CELL *);
  36.  
  37. extern void sort EXT4(int, int(*)(int,int),void(*)(int,int),void(*)(int,int));
  38. extern char *set_new_value EXT4(CELLREF, CELLREF, int, union vals *);
  39. extern char *new_value EXT3(CELLREF, CELLREF, char *);
  40.  
  41. extern void flush_old_value EXT0();
  42.  
  43. extern void move_cell EXT4(CELLREF, CELLREF, CELLREF, CELLREF);
  44.  
  45. extern void push_refs EXT1(struct ref_fm *);
  46. extern void push_cell EXT2(CELLREF, CELLREF);
  47.  
  48. extern CELL *my_cell;
  49. extern int modified;
  50. extern CELLREF cur_row,cur_col;
  51.  
  52. struct rng all_rng = { MIN_ROW, MIN_COL, MAX_ROW, MAX_COL };
  53.  
  54. /* Take a struct rng (R) and init its elements to R1 C1 R2 C2, making sure
  55.    they are put in in the right order.
  56.  */
  57. void
  58. set_rng FUN5(struct rng *,r, CELLREF,r1, CELLREF,c1, CELLREF,r2, CELLREF,c2)
  59. {
  60.     if(r1<=r2) {
  61.         r->lr=r1;
  62.         r->hr=r2;
  63.     } else {
  64.         r->lr=r2;
  65.         r->hr=r1;
  66.     }
  67.     if(c1<=c2) {
  68.         r->lc=c1;
  69.         r->hc=c2;
  70.     } else {
  71.         r->lc=c2;
  72.         r->hc=c1;
  73.     }
  74. }
  75.  
  76. /* Flush all the cells in a region */
  77. void
  78. delete_region FUN1(struct rng *,where)
  79. {
  80.     CELLREF rr,cc;
  81.     CELL *pp;
  82.  
  83.     modified=1;
  84.  
  85.     find_cells_in_range(where);
  86.     while(pp=next_row_col_in_range(&rr,&cc)) {
  87.         if(!pp->cell_formula && !GET_TYP(pp)) {
  88.             pp->cell_flags=0;
  89.             continue;
  90.         }
  91.         cur_row=rr;
  92.         cur_col=cc;
  93.         my_cell=pp;
  94.         flush_old_value();
  95.         pp->cell_formula=0;
  96.         pp->cell_flags=0;
  97.         push_refs(pp->cell_refs_from);
  98.         pr_cell(rr,cc,pp);
  99.     }
  100.     my_cell=0;
  101. }
  102.  
  103. /* Turn on/off the locked bits in a region */
  104. void
  105. lock_region FUN2(struct rng *,where, int,locked)
  106. {
  107.     CELL *cp;
  108.  
  109.     modified=1;
  110.     make_cells_in_range(where);
  111.     while(cp=next_cell_in_range())
  112.         SET_LCK(cp,locked);
  113. }
  114.  
  115. void
  116. format_region FUN3(struct rng *,where, int,fmt, int,just)
  117. {
  118.     CELL *cp;
  119.     CELLREF rr,cc;
  120.  
  121.     modified=1;
  122.     make_cells_in_range(where);
  123.     while(cp=next_row_col_in_range(&rr,&cc)) {
  124.         if(fmt!=-1)
  125.             SET_FMT(cp,fmt);
  126.         if(just!=-1)
  127.             SET_JST(cp,just);
  128.         pr_cell(rr,cc,cp);
  129.     }
  130. }
  131.  
  132. unsigned short print_width;
  133.  
  134. void
  135. print_region FUN2(FILE *,fp, struct rng *,print)
  136. {
  137.     CELLREF rr,cc;
  138.     CELL *cp;
  139.     char *ptr;
  140.     int w;
  141.     int j;
  142.     int lenstr;
  143.     int spaces;
  144.     CELLREF c_lo,c_hi;
  145.  
  146.     extern int default_jst, default_fmt;
  147.  
  148.     for(c_lo=print->lc,c_hi=0;c_hi!=print->hc;c_lo=c_hi+1) {
  149.         w=0;
  150.         for(w=get_width(cc=c_lo);w<=print_width && cc<=print->hc;w+=get_width(++cc))
  151.             ;
  152.         if(cc!=c_lo)
  153.             --cc;
  154.         c_hi=cc;
  155.         
  156.         for(rr=print->lr;rr<=print->hr;rr++) {
  157.             spaces=0;
  158.             for(cc=c_lo;cc<=c_hi;cc++) {
  159.                 w=get_width(cc);
  160.                 if(!w)
  161.                     continue;
  162.                 cp=find_cell(rr,cc);
  163.                 if(!cp || !GET_TYP(cp)) {
  164.                     spaces+=w;
  165.                     continue;
  166.                 }
  167.                 ptr=print_cell(cp);
  168.                 lenstr=strlen(ptr);
  169.                 if(lenstr==0) {
  170.                     spaces+=w;
  171.                     continue;
  172.                 }
  173.                 if(spaces) {
  174.                     fprintf(fp,"%*s",spaces,"");
  175.                     spaces=0;
  176.                 }
  177.                 j=GET_JST(cp);
  178.                 if(j==JST_DEF)
  179.                     j=default_jst;
  180.                 if(lenstr<=w-1) {
  181.                     if(j==JST_LFT) {
  182.                         fprintf(fp,"%s",ptr);
  183.                         spaces=w-lenstr;
  184.                     } else if(j==JST_RGT) {
  185.                         fprintf(fp,"%*s",w-1,ptr);
  186.                         spaces=1;
  187.                     } else if(j==JST_CNT) {
  188.                         w=(w-1)-lenstr;
  189.                         fprintf(fp,"%*s",w/2+lenstr,ptr);
  190.                         spaces=(w+3)/2;
  191.                     }
  192. #ifdef TEST
  193.                     else {
  194.                         panic("What just %d",j);
  195.                     }
  196. #endif
  197.                 } else {
  198.                     CELLREF ccc=cc;
  199.                     CELL *ccp;
  200.                     int tmp_wid;
  201.                     unsigned short ww;
  202.                     extern char numb_oflo[];
  203.  
  204.                     for(ww=w;;tmp_wid=get_width(ccc),w+=tmp_wid,spaces-=tmp_wid) {
  205.                         if(lenstr<w-1)
  206.                             break;
  207.                         if(++ccc>c_hi)
  208.                             break;
  209.                         ccp=find_cell(rr,ccc);
  210.                         if(!ccp || !GET_TYP(ccp) || GET_FMT(ccp)==FMT_HID)
  211.                             continue;
  212.                         if(GET_FMT(ccp)==FMT_DEF && default_fmt==FMT_HID)
  213.                             continue;
  214.                         break;
  215.                     }
  216.                     if(lenstr>w-1) {
  217.                         extern char *adjust_prc EXT5(char *, CELL *, int, int, int);
  218.  
  219.                         if(GET_TYP(cp)==TYP_FLT) {
  220.                             ptr=adjust_prc(ptr,cp,w-1,ww-1,j);
  221.                             lenstr=strlen(ptr);
  222.                         } else if(GET_TYP(cp)==TYP_INT) {
  223.                             ptr=numb_oflo;
  224.                             lenstr=80;
  225.                         }
  226.                         fprintf(fp,"%.*s",w-1,ptr);
  227.                         if(lenstr<w)
  228.                             spaces+=w-lenstr;
  229.                         else
  230.                             spaces++;
  231.                     } else {
  232.                         fprintf(fp,"%s",ptr);
  233.                         spaces+=w-lenstr;
  234.                     }
  235.                 }
  236.             }
  237.             (void)putc('\n',fp);
  238.         }
  239.     }
  240. }
  241.  
  242.  
  243. /*
  244.    Set up regions for the move/copy functions.  This deals with default
  245.    sizing of the target region, regions that don't fit, etc.
  246.  
  247.    This returns
  248.     -1 if the regions overlap
  249.     0 if there is a *real* error
  250.     1 if the target is a multiple of the source
  251.     2 if everything is OK.
  252.  */
  253.  
  254. static int
  255. set_to_region FUN2(struct rng *,fm, struct rng *,to)
  256. {
  257.     /* Delta {row,col} {from,to} */
  258.     int drf, dcf;
  259.     int drt, dct;
  260.     int ret = 2;
  261.  
  262.     drf=fm->hr-fm->lr;
  263.     drt=to->hr-to->lr;
  264.     if(drt==0) {
  265.         if(to->lr>MAX_ROW-drf) {
  266.             error_msg("The range won't fit this far down!");
  267.             return 0;
  268.         }
  269.         to->hr=to->lr+drf;
  270.     } else if(drf!=drt) {
  271.         if((drt+1)%(drf+1)==0)
  272.             ret=1;
  273.         else {
  274.             error_msg("Rows %u:%u and %u:%u don't fit",fm->lr,fm->hr,to->lr,to->hr);
  275.             return 0;
  276.         }
  277.     }
  278.     dcf=fm->hc-fm->lc;
  279.     dct=to->hc-to->lc;
  280.     if(dct==0) {
  281.         if(to->lc>MAX_COL-dcf) {
  282.             error_msg("The range won't fit this far over!");
  283.             return 0;
  284.         }
  285.         to->hc=to->lc+dcf;
  286.     } else if(dcf!=dct) {
  287.         if((dct+1)%(dcf+1)==0)
  288.             ret=1;
  289.         else {
  290.             error_msg("Cols %u:%u and %u:%u don't fit",fm->lc,fm->hc,to->lc,to->hc);
  291.             return 0;
  292.         }
  293.     }
  294.  
  295.     if(fm->lr==to->lr && fm->lc==to->lc) {
  296.         error_msg("Regions are in the same place");
  297.         return 0;
  298.     }
  299.         
  300.     if(((fm->lr<=to->lr && to->lr<=fm->hr) || (fm->lr<=to->hr && to->hr<=fm->hr))
  301.      &&((fm->lc<=to->lc && to->lc<=fm->hc) || (fm->lc<=to->hc && to->hc<=fm->hc)))
  302.         return -1;
  303.     modified=1;
  304.     return ret;
  305. }
  306.  
  307. /* This is only complicated because it must deal with overlap, and it wants
  308.    to be smart about copying empty space. . .
  309.  */
  310. void
  311. move_region FUN2(struct rng *,fm, struct rng *,to)
  312. {
  313.     /* Delta {row,col} */
  314.     int dr,dc;
  315.     int nr,nc;
  316.     int ov,dn;
  317.     struct rng del_to_1,del_to_2;
  318.     int do_2,dirs[2];
  319.     int maxr,maxc;
  320.     CELLREF cmax,rmax;
  321.     int cdmax,rdmax;
  322.     int ret = 0;
  323.     extern void shift_widths EXT1(int);
  324.     extern void shift_outside EXT3(struct rng *,int, int);
  325.  
  326.     switch(set_to_region(fm,to)) {
  327.     case 0:
  328.         return;
  329.  
  330.     case 1:
  331.         error_msg("Can't move source to multiple targets");
  332.         return;
  333.  
  334.     case 2:
  335.         del_to_1= *to;
  336.  
  337.         do_2=0;
  338.         dirs[0]=1;
  339.         dirs[1]=1;
  340.  
  341.         /* del_fm_1= *fm; */
  342.         break;
  343.  
  344.     default:
  345.         /* They overlap.  There are eight ways that
  346.            they can overlap.  */
  347.         if(to->lc==fm->lc && to->lr<fm->lr) {
  348.                /* State 1:  'from' on bottom */
  349.             del_to_1.lr=to->lr;    del_to_1.lc=to->lc;
  350.             del_to_1.hr=fm->lr-1;    del_to_1.hc=to->hc;
  351.  
  352.             do_2=0;
  353.             dirs[0]=1;
  354.             dirs[1]=1;
  355.  
  356.             /* del_fm_1.lr=to->hr+1;    del_fm_1.lc=fm->lc;
  357.             del_fm_1.hr=fm->hr;    del_fm_1.hc=fm->hc; */
  358.         } else if(to->lc==fm->lc) {
  359.             /* State 2: 'from' on top */
  360.             del_to_1.lr=fm->hr+1;    del_to_1.lc=to->lc;
  361.             del_to_1.hr=to->hr;    del_to_1.hc=to->hc;
  362.  
  363.             do_2=0;
  364.             dirs[0]= -1;
  365.             dirs[1]=  1;
  366.  
  367.             /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  368.             del_fm_1.hr=to->lr-1;    del_fm_1.hc=fm->hc; */
  369.         } else if(to->lr==fm->lr && to->lc<fm->lc) {
  370.             /* State 3: 'from' on right */
  371.             del_to_1.lr=to->lr;    del_to_1.lc=to->lc;
  372.             del_to_1.hr=to->hr;    del_to_1.hc=fm->lc-1;
  373.  
  374.             do_2=0;
  375.             dirs[0]=1;
  376.             dirs[1]=1;
  377.  
  378.             /* del_fm_1.lr=fm->lr;    del_fm_1.lc=to->hc+1;
  379.             del_fm_1.hr=fm->hr;    del_fm_1.hc=fm->hc; */
  380.         } else if(to->lr==fm->lr) {
  381.             /* State 4: 'from' on left */
  382.             del_to_1.lr=to->lr;    del_to_1.lc=fm->hc+1;
  383.             del_to_1.hr=to->hr;    del_to_1.hc=to->hc;
  384.  
  385.             do_2=0;
  386.             dirs[0]= 1;
  387.             dirs[1]= -1;
  388.  
  389.             /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  390.             del_fm_1.hr=fm->hr;    del_fm_1.hc=to->lc-1; */
  391.         } else if(fm->lr<to->lr && fm->lc<to->lc) {
  392.             /* State 5: From on topleft */
  393.  
  394.             del_to_1.lr=to->lr;    del_to_1.lc=fm->hc+1;
  395.             del_to_1.hr=fm->hr;    del_to_1.hc=to->hc;
  396.  
  397.             del_to_2.lr=fm->hr+1;    del_to_2.lc=to->lc;
  398.             del_to_2.hr=to->hr;    del_to_2.hc=to->hc;
  399.  
  400.             do_2=1;
  401.             dirs[0]= -1;
  402.             dirs[1]= -1;
  403.  
  404.             /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  405.             del_fm_1.hr=to->lr-1;    del_fm_1.hc=fm->hc;
  406.  
  407.             del_fm_2.lr=to->lr;    del_fm_2.lc=fm->lc;
  408.             del_fm_2.hr=fm->hr;    del_fm_2.hc=to->lc-1; */
  409.         } else if(fm->lr<to->lr) {
  410.             /* State 6: 'from' on topright */
  411.             del_to_1.lr=to->lr;    del_to_1.lc=to->lc;
  412.             del_to_1.hr=fm->hr;    del_to_1.hc=fm->lc-1;
  413.  
  414.             del_to_2.lr=fm->hr+1;    del_to_2.lc=to->lc;
  415.             del_to_2.hr=to->hr;    del_to_2.hc=to->hc;
  416.  
  417.             do_2=1;
  418.             dirs[0]= -1;
  419.             dirs[1]=  1;
  420.  
  421.             /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  422.             del_fm_1.hr=to->lr-1;    del_fm_1.hc=fm->hc;
  423.  
  424.             del_fm_2.lr=to->lr;    del_fm_2.lc=to->hc+1;
  425.             del_fm_2.hr=fm->hr;    del_fm_2.hc=fm->hc; */
  426.         } else if(fm->lc<to->lc) {
  427.             /* State 7: 'from on bottomleft */
  428.             del_to_1.lr=to->lr;    del_to_1.lc=to->lc;
  429.             del_to_1.hr=fm->lr-1;    del_to_1.hc=to->hc;
  430.  
  431.             del_to_2.lr=fm->lr;    del_to_2.lc=fm->hc;
  432.             del_to_2.hr=to->hr;    del_to_2.hc=to->hc;
  433.  
  434.             do_2=1;
  435.             dirs[0]=  1;
  436.             dirs[1]= -1;
  437.  
  438.             /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  439.             del_fm_1.hr=to->hr;    del_fm_1.hc=to->lc-1;
  440.  
  441.             del_fm_2.lr=to->hr+1;    del_fm_2.lc=fm->lc;
  442.             del_fm_2.hr=to->hr+1;    del_fm_2.hc=to->lc-1; */
  443.         } else {
  444.             /* State 8: 'from' on bottomright */
  445.             del_to_1.lr=to->lr;    del_to_1.lc=to->lc;
  446.             del_to_1.hr=fm->lr-1;    del_to_1.hc=to->hc;
  447.  
  448.             del_to_2.lr=fm->lr;    del_to_2.lc=to->lc;
  449.             del_to_2.hr=to->hr;    del_to_2.hc=fm->lc-1;
  450.  
  451.             do_2=1;
  452.             dirs[0]=1;
  453.             dirs[1]=1;
  454.  
  455.             /* del_fm_1.lr=fm->lr;    del_fm_1.lc=to->hc+1;
  456.             del_fm_1.hr=to->hr;    del_fm_1.hc=fm->hc;
  457.  
  458.             del_fm_2.lr=to->hr+1;    del_fm_2.lc=fm->lc;
  459.             del_fm_2.hr=fm->hr;    del_fm_2.hc=fm->hc; */
  460.         }
  461.     }
  462.     dn=to->hr-fm->hr;
  463.     ov=to->hc-fm->hc;
  464.  
  465.     dr=fm->hr-fm->lr;
  466.     dc=fm->hc-fm->lc;
  467.  
  468.     delete_region(&del_to_1);
  469.     if(do_2)
  470.         delete_region(&del_to_2);
  471.  
  472.     if(to->lr==MIN_ROW && to->hr==MAX_ROW) {
  473.         shift_widths(ov);
  474.         ret=1;
  475.     }
  476.  
  477.     shift_outside(fm,dn,ov);
  478.  
  479. #ifdef REVERSE
  480.     cmax=max_col(fm->lr);
  481.     if(cmax<fm->lc)
  482.         cdmax= -1;
  483.     else if(cmax>fm->hc)
  484.         cdmax=dc;
  485.     else {
  486.         cdmax=cmax-fm->lc;
  487.     }
  488.     nc=(dirs[1]>0) ? 0 : cdmax;
  489.     maxc= (dirs[1]>0) ? cdmax+1 : -1;
  490.     for(;nc!=maxc;nc+=dirs[1]) {
  491.         rmax=max_row(fm->lc+nc);
  492.         if(rmax<fm->lr)
  493.             rdmax= -1;
  494.         else if(rmax>fm->hr)
  495.             rdmax=dr;
  496.         else
  497.             rdmax=rmax-fm->lr;
  498.         nr= (dirs[0]>0) ? 0 : rdmax;
  499.         maxr= (dirs[0]>0) ? rdmax+1 : -1;
  500.         for(;nr!=maxr;nr+=dirs[0])
  501. #else
  502.     rmax=max_row(fm->hc);
  503.     if(rmax<fm->lr)
  504.         rdmax= -1;
  505.     else if(rmax>fm->hr)
  506.         rdmax=dr;
  507.     else
  508.         rdmax=rmax-fm->lr;
  509.     nr= (dirs[0]>0) ? 0 : rdmax;
  510.     maxr= (dirs[0]>0) ? rdmax+1 : -1;
  511.     for(;nr!=maxr;nr+=dirs[0]) {
  512.         cmax=max_col(fm->lr+nr);
  513.         if(cmax<fm->lc)
  514.             cdmax= -1;
  515.         else if(cmax>fm->hc)
  516.             cdmax=dc;
  517.         else {
  518.             cdmax=cmax-fm->lc;
  519.         }
  520.         nc=(dirs[1]>0) ? 0 : cdmax;
  521.         maxc= (dirs[1]>0) ? cdmax+1 : -1;
  522.         for(;nc!=maxc;nc+=dirs[1])
  523. #endif
  524.         {
  525.             CELLREF rf,cf,rt,ct;
  526.             CELL *cpf;
  527.  
  528.             rf=fm->lr+nr;
  529.             cf=fm->lc+nc;
  530.             rt=to->lr+nr;
  531.             ct=to->lc+nc;
  532.  
  533.             cpf=find_cell(rf,cf);
  534.             cur_row=rt;
  535.             cur_col=ct;
  536.             my_cell=find_cell(cur_row,cur_col);
  537.             if((!cpf || (!cpf->cell_flags && !cpf->cell_formula)) && !my_cell)
  538.                 continue;
  539.  
  540.             if(!cpf) {
  541.                 my_cell->cell_flags=0;
  542.                 my_cell->cell_refs_to=0;
  543.                 my_cell->cell_formula=0;
  544.                 my_cell->cell_cycle=0;
  545.                 my_cell=0;
  546.                 continue;
  547.             }
  548.             if(!my_cell) {
  549.                 my_cell=find_or_make_cell(cur_row,cur_col);
  550.                 cpf=find_cell(rf,cf);
  551.             } else
  552.                 flush_old_value();
  553.  
  554.             my_cell->cell_flags=cpf->cell_flags;
  555.             my_cell->cell_refs_to=cpf->cell_refs_to;
  556.             my_cell->cell_formula=cpf->cell_formula;
  557.             my_cell->cell_cycle=cpf->cell_cycle;
  558.             my_cell->c_z=cpf->c_z;
  559.  
  560.             cpf->cell_flags=0;
  561.             cpf->cell_refs_to=0;
  562.             cpf->cell_formula=0;
  563.             cpf->cell_cycle=0;
  564.  
  565.             push_refs(my_cell->cell_refs_from);
  566.  
  567.             if(!ret) {
  568.                 if(cpf)
  569.                     pr_cell(rf,cf,cpf);
  570.                 if(my_cell)
  571.                     pr_cell(rt,ct,my_cell);
  572.             }
  573.             my_cell=0;
  574.         }
  575.     }
  576.     return;
  577. }
  578.  
  579. void
  580. copy_region FUN2(struct rng *,fm, struct rng *,to)
  581. {
  582.     CELLREF rf,rt,cf,ct;
  583.     /* CELL *cpf; */
  584.     /* char *dec; */
  585.     /* int f,j,p; */
  586.     extern void set_cell EXT3(CELLREF, CELLREF, char *);
  587.     extern void update_cell EXT1(CELL *);
  588.  
  589.     if(set_to_region(fm,to)<1)
  590.         return;
  591.  
  592.     for(rf=fm->lr,rt=to->lr;rt<=to->hr;rt++,rf++) {
  593.         for(cf=fm->lc,ct=to->lc;ct<=to->hc;ct++,cf++) {
  594.             copy_cell(rf,cf,rt,ct);
  595. #if 0
  596.             cpf=find_cell(rf,cf);
  597.             f = (cpf) ? GET_FMT(cpf) : FMT_DEF;
  598.             j = (cpf) ? GET_JST(cpf) : JST_DEF;
  599.  
  600.             if(!cpf || (!GET_TYP(cpf) && !cpf->cell_formula)) {
  601.                 cur_row=rt;
  602.                 cur_col=ct;
  603.                 my_cell=find_cell(cur_row,cur_col);
  604.                 if(my_cell)
  605.                     flush_old_value();
  606.             } else {
  607.                 dec=decomp(rf,cf,cpf);
  608.                 set_cell(rt,ct,dec);
  609.                 decomp_free();
  610.             }
  611.             if(my_cell) {
  612.                 SET_FMT(my_cell,f);
  613.                 SET_JST(my_cell,j);
  614.                 /* SET_PRC(cpt,p); */
  615.  
  616.                 update_cell(my_cell);
  617.                 pr_cell(cur_row,cur_col,my_cell);
  618.                 my_cell=0;
  619.             }
  620. #endif
  621.  
  622.             if(cf==fm->hc)
  623.                 cf=fm->lc-1;
  624.         }
  625.         if(rf==fm->hr)
  626.             rf=fm->lr-1;
  627.     }
  628. }
  629.  
  630. void
  631. copy_values_region FUN2(struct rng *,fm, struct rng *,to)
  632. {
  633.     CELLREF rf,rt,cf,ct;
  634.     union vals dummy;
  635.     CELL *cpf;
  636.  
  637.     if(set_to_region(fm,to)<1)
  638.         return;
  639.  
  640.     for(rf=fm->lr,rt=to->lr;rt<=to->hr;rt++,rf++) {
  641.         for(cf=fm->lc,ct=to->lc;ct<=to->hc;ct++,cf++) {
  642.             cpf=find_cell(rf,cf);
  643.             set_new_value(rt, ct, cpf ? GET_TYP(cpf) : 0, cpf ? &(cpf->c_z) : &dummy);
  644.  
  645.             if(cf==fm->hc)
  646.                 cf=fm->lc-1;
  647.         }
  648.         if(rf==fm->hr)
  649.             rf=fm->lr-1;
  650.     }
  651. }
  652.  
  653. /* Sorting is complicated */
  654. /* Sorting requires lots of state information. . . */
  655.  
  656. struct cmp {
  657.     char mult;
  658.     CELLREF row;
  659.     CELLREF col;
  660. };
  661.  
  662. struct rng sort_rng;
  663. struct rng sort_ele;
  664. struct cmp *sort_keys;
  665. int sort_keys_alloc;
  666. int sort_keys_num = 0;
  667.  
  668. static int srdiff,erdiff,scdiff,ecdiff;
  669. static int cmp_cells EXT2(int,int);
  670. static void swp_cells EXT2(int,int);
  671. static void rot_cells EXT2(int,int);
  672.  
  673. #ifdef TEST
  674. extern int debug;
  675. #endif
  676.  
  677. void
  678. sort_region FUN0()
  679. {
  680.     srdiff = 1+sort_rng.hr-sort_rng.lr;
  681.     erdiff = 1+sort_ele.hr-sort_ele.lr;
  682.  
  683.     scdiff = 1+sort_rng.hc-sort_rng.lc;
  684.     ecdiff = 1+sort_ele.hc-sort_ele.lc;
  685.  
  686.     if(srdiff!=erdiff && srdiff%erdiff!=0) {
  687.         error_msg("Rows %u:%u and %u:%u don't fit",sort_rng.lr,sort_rng.hr,sort_ele.lr,sort_ele.hr);
  688.         return;
  689.     }
  690.     if(scdiff!=ecdiff && scdiff%ecdiff!=0) {
  691.         error_msg("Cols %u:%u and %u:%u don't fit",sort_rng.lc,sort_rng.hc,sort_ele.lc,sort_ele.hc);
  692.         return;
  693.     }
  694.     if(scdiff!=ecdiff && srdiff!=erdiff) {
  695.         error_msg("Can't sort this region!");
  696.         return;
  697.     }
  698.     modified=1;
  699.     if(scdiff!=ecdiff) {
  700.         erdiff=0;
  701.         sort(scdiff/ecdiff,cmp_cells,swp_cells,rot_cells);
  702.     } else {
  703.         ecdiff=0;
  704.         sort(srdiff/erdiff,cmp_cells,swp_cells,rot_cells);
  705.     }
  706. }
  707.  
  708. static int
  709. cmp_cells FUN2(int,n1, int,n2)
  710. {
  711.     CELL *c1,*c2;
  712.     int t1,t2;
  713.     union vals v1,v2;
  714.     CELLREF row1,row2,col1,col2;
  715.     int keyn;
  716.     int cmpval;
  717.  
  718.     if(n1==n2)
  719.         return 0;
  720.  
  721.     for(keyn=0;keyn<sort_keys_num;keyn++) {
  722.         row1=sort_rng.lr+(n1*erdiff)+sort_keys[keyn].row;
  723.         col1=sort_rng.lc+(n1*ecdiff)+sort_keys[keyn].col;
  724.         row2=sort_rng.lr+(n2*erdiff)+sort_keys[keyn].row;
  725.         col2=sort_rng.lc+(n2*ecdiff)+sort_keys[keyn].col;
  726. #ifdef TEST
  727.         if(debug&04)
  728.             error_msg("Cmp %u %u  r%uc%u <-%u-> r%uc%u",n1,n2,row1,col1,sort_keys[keyn].mult,row2,col2);
  729. #endif
  730.         c1=find_cell(row1,col1);
  731.         c2=find_cell(row2,col2);
  732.         if(!c1 && !c2)
  733.             continue;
  734.  
  735.         if(c1) {
  736.             t1= GET_TYP(c1);
  737.             v1=c1->c_z;
  738.         } else
  739.             t1=0;
  740.         if(c2) {
  741.             t2= GET_TYP(c2);
  742.             v2=c2->c_z;
  743.         } else
  744.             t2=0;
  745.  
  746.         if(t1==TYP_ERR || t1==TYP_BOL) {
  747.             t1=TYP_STR;
  748.             v1.c_s=print_cell(c1);
  749.         }
  750.         if(t2==TYP_ERR || t2==TYP_BOL) {
  751.             t2=TYP_STR;
  752.             v2.c_s=print_cell(c2);
  753.         }
  754.         if(t1!=t2) {
  755.             if(t1==0) {
  756.                 if(t2==TYP_STR) {
  757.                     t1=TYP_STR;
  758.                     v1.c_s="";
  759.                 } else if(t2==TYP_INT) {
  760.                     t1=TYP_INT;
  761.                     v1.c_l=0;
  762.                 } else {
  763.                     t1=TYP_FLT;
  764.                     v1.c_d=0.0;
  765.                 }
  766.             } else if(t2==0) {
  767.                 if(t1==TYP_STR) {
  768.                     t2=TYP_STR;
  769.                     v2.c_s="";
  770.                 } else if(t1==TYP_INT) {
  771.                     t2=TYP_INT;
  772.                     v2.c_l=0;
  773.                 } else {
  774.                     t2=TYP_FLT;
  775.                     v2.c_d=0.0;
  776.                 }
  777.             } else if(t1==TYP_STR) {
  778.                 t2=TYP_STR;
  779.                 v2.c_s=print_cell(c2);
  780.             } else if(t2==TYP_STR) {
  781.                 t1=TYP_STR;
  782.                 v1.c_s=print_cell(c1);
  783.             /* If we get here, one is INT, and the other
  784.                is FLT  Make them both FLT */
  785.             } else if(t1==TYP_INT) {
  786.                 t1=TYP_FLT;
  787.                 v1.c_d=(double)v1.c_l;
  788.             } else {
  789.                 t2=TYP_FLT;
  790.                 v2.c_d=(double)v2.c_l;
  791.             }
  792.         }
  793.         if(t1==TYP_STR)
  794.             cmpval=strcmp(v1.c_s,v2.c_s);
  795.         else if(t1==TYP_FLT)
  796.             cmpval=(v1.c_d < v2.c_d) ? -1 : ((v1.c_d>v2.c_d) ? 1 : 0);
  797.         else if(t1==TYP_INT)
  798.             cmpval=(v1.c_l < v2.c_l) ? -1 : ((v1.c_l>v2.c_l) ? 1 : 0);
  799.         else
  800.             cmpval = 0;
  801.         if(cmpval)
  802.             return cmpval*sort_keys[keyn].mult;
  803.     }
  804.  
  805.     return 0;
  806. }
  807.  
  808. static void
  809. swp_cells FUN2(int,n1, int,n2)
  810. {
  811.     int rn,cn;
  812.     CELLREF r1,r2,c1,c2;
  813.  
  814. #ifdef TEST
  815.     if(debug&04)
  816.         error_msg("Swap %u<-->%u",n1,n2);
  817. #endif
  818.     for(rn=sort_ele.lr;rn<=sort_ele.hr;rn++)
  819.         for(cn=sort_ele.lc;cn<=sort_ele.hc;cn++) {
  820.             r1=sort_rng.lr+(n1*erdiff)+rn;
  821.             r2=sort_rng.lr+(n2*erdiff)+rn;
  822.             c1=sort_rng.lc+(n1*ecdiff)+cn;
  823.             c2=sort_rng.lc+(n2*ecdiff)+cn;
  824. #ifdef TEST
  825.             if(debug&04)
  826.                 error_msg("Save  r%uc%u",r1,c1);
  827. #endif
  828.             move_cell(r1,c1,NON_ROW,NON_COL);
  829. #ifdef TEST
  830.             if(debug&04)
  831.                 error_msg("Copy r%uc%u --> r%uc%u",r2,c2,r1,c1);
  832. #endif
  833.             move_cell(r2,c2,r1,c1);
  834.  
  835. #ifdef TEST
  836.             if(debug&04)
  837.                 error_msg("Restore r%uc%u",r2,c2);
  838. #endif
  839.             move_cell(NON_ROW,NON_COL,r2,c2);
  840.  
  841.             /* push_cell(r1,c1);
  842.             push_cell(r2,c2); */
  843.         }
  844. }
  845.  
  846. static void
  847. rot_cells FUN2(int,n1, int,n2)
  848. {
  849.     int rn,cn;
  850.     int nn;
  851.     CELLREF r1,r2,c1,c2;
  852.  
  853.     if(n1+1==n2 || n2+1 == n1) {
  854.         swp_cells(n1,n2);
  855.         return;
  856.     }
  857. #ifdef TEST
  858.     if(debug&04)
  859.         error_msg("Rot cells %u -- %u",n1,n2);
  860. #endif
  861.     for(rn=sort_ele.lr;rn<=sort_ele.hr;rn++)
  862.         for(cn=sort_ele.lc;cn<=sort_ele.hc;cn++) {
  863.  
  864.             /* store a copy of cell # n2 */
  865.             r2=sort_rng.lr+(n2*erdiff)+rn;
  866.             c2=sort_rng.lc+(n2*ecdiff)+cn;
  867.             move_cell(r2,c2,NON_ROW,NON_COL);
  868.  
  869. #ifdef TEST
  870.             if(debug&04)
  871.                 error_msg("Save r%uc%u",r2,c2);
  872. #endif
  873.             /* Copy each cell from n1 to n2-1 up one */
  874.             for(nn=n2;nn>n1;--nn) {
  875.                 r2=sort_rng.lr+(nn*erdiff)+rn;
  876.                 c2=sort_rng.lc+(nn*ecdiff)+cn;
  877.  
  878.                 r1=sort_rng.lr+((nn-1)*erdiff)+rn;
  879.                 c1=sort_rng.lc+((nn-1)*ecdiff)+cn;
  880.  
  881.                 move_cell(r1,c1,r2,c2);
  882. #ifdef TEST
  883.                 if(debug&04)
  884.                     error_msg("Copy r%uc%u --> r%uc%u",r1,c1,r2,c2);
  885. #endif
  886.                 /* push_cell(r2,c2); */
  887.             }
  888.  
  889.             r1=sort_rng.lr+(nn*erdiff)+rn;
  890.             c1=sort_rng.lc+(nn*ecdiff)+cn;
  891. #ifdef TEST
  892.             if(debug&04)
  893.                 error_msg("Restore r%uc%u",r1,c1);
  894. #endif
  895.             move_cell(NON_ROW,NON_COL,r1,c1);
  896.  
  897.             /* push_cell(r1,c1); */
  898.         }
  899. }
  900.  
  901. /* End of functions for sort_region() */
  902.